package atlantik.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;

import atlantik.game.Atlantik;
import atlantik.game.Estate;
import atlantik.game.EstateGroup;
import atlantik.game.Player;

public class PlayerView extends JComponent {

	private static final long serialVersionUID = 6009335074727417445L;

	private static final int BORDER_WIDTH = 3;

	private static final int CARD_HEIGHT = 18;

	private static final int CARD_WIDTH = 12;

	private static final int CARD_OFFSET_X = 3;

	private static final int CARD_OFFSET_Y = 4;

	private static final int MAX_CARDS = 5; // TODO remove this hard limit

	private static final Rectangle2D BACKGROUND = new Rectangle2D.Double(0, 0, 1, 1);

	private final Player item;

	private final Atlantik client;

	public PlayerView(Atlantik client, Player item) {
		this.client = client;
		this.item = item;
	}

	public void updateSize() {
		if( ! isDisplayable() )
			return;
		
		FontMetrics fm = getFontMetrics(getFont());
		int tw = item.getToken().getWidth(this);
		int th = item.getToken().getHeight(this);

		int titleWidth = 0;
		if (item.getName() != null)
			titleWidth = fm.stringWidth(item.getName());
		titleWidth += fm.stringWidth(Integer.toString(item.getMoney()));
		titleWidth += BORDER_WIDTH * 3;
		int w = CARD_WIDTH * client.getState().estateGroups().size() + CARD_OFFSET_X * client.getState().estates().size();
		w += BORDER_WIDTH * 2;
		if (titleWidth > w)
			w = titleWidth;
		w += BORDER_WIDTH * 2;
		w += tw;

		int h = fm.getMaxAscent() + fm.getMaxDescent();
		h += CARD_HEIGHT + CARD_OFFSET_Y * (MAX_CARDS - 1);
		h += BORDER_WIDTH * 2;
		if (h < th)
			h = th;
		h += BORDER_WIDTH * 2;

		setPreferredSize(new Dimension(w, h));
	}

	public void paintComponent(Graphics gr) {
		Graphics2D g = (Graphics2D) gr;
		AffineTransform scale = AffineTransform.getScaleInstance(getWidth(),
				getHeight());

		Shape bg = scale.createTransformedShape(BACKGROUND);
		if (item.hasTurn())
			if (item.hasDebt())
				g.setColor(Color.RED);
			else
				g.setColor(Color.BLUE);
		else
			g.setColor(Color.BLACK);
		g.fill(bg);

		g.drawImage(item.getToken(), 0, BORDER_WIDTH, this);

		// the player name
		g.setColor(Color.WHITE);
		FontMetrics fm = getFontMetrics(getFont());
		int minWidth = 3;
		if( item.getToken() != null )
			minWidth = item.getToken().getWidth(this);
		
		int x = minWidth + BORDER_WIDTH;
		int y = fm.getMaxAscent() + BORDER_WIDTH;
		if (item.getName() != null)
			g.drawString(item.getName(), x, y);

		// right align money
		String moneyString = Integer.toString(item.getMoney());
		g.drawString(moneyString, getWidth() - BORDER_WIDTH
				- fm.stringWidth(moneyString), y);

		// background for card table
		y += fm.getMaxDescent() + BORDER_WIDTH;
		g.fillRect(x, y, getWidth() - BORDER_WIDTH, getHeight() - BORDER_WIDTH);

		// card table
		y += BORDER_WIDTH;
		x += BORDER_WIDTH;
		for (EstateGroup group : client.getState().estateGroups()) {
			int oy = 0;
			for (Estate estate : group) {
				g.setColor(estate.getBackgroundColor().darker());
				g.fillRect(x, y + oy, CARD_WIDTH, CARD_HEIGHT);

				// Group color if owned by player
				if (estate.getOwner() == item) {
					Color fg = estate.getColor();
					if (fg == null)
						fg = Color.BLACK;

					// bright Frame to highlight dark color
					g.setColor(Color.WHITE);
					g.fillRect(x + 1, y + oy + 1, CARD_WIDTH - 2,
							CARD_OFFSET_Y - 1);

					g.setColor(fg);
					g.fillRect(x + 2, y + oy + 1, CARD_WIDTH - 4,
							CARD_OFFSET_Y - 1);
				}

				// mortgage indicator
				g.setColor((estate.isMortgaged() ? Color.BLACK : Color.WHITE));
				g.fillRect(x + 1, y + oy + CARD_OFFSET_Y, CARD_WIDTH - 2,
						CARD_HEIGHT - CARD_OFFSET_Y - 1);

				oy += CARD_OFFSET_Y;
				x += CARD_OFFSET_X;
			}
			x += CARD_WIDTH;
		}
	}

}
